#include <i386/stdlib.h>
#include <i386/string.h>
#include <i386/limits.h>
#include <stdarg.h>
#include <ctype.h>
#include "sprintf.h"

int vsscanf(char *buf, char *fmt, va_list parms) {
	int scanned = 0, size = 0, suppress = 0;
	int w = 0, flag = 0, l = 0;
	char c, *c_ptr;
	long int n1, *n1l;
	int *n1b;
	short int *n1s;
	long unsigned n2, *n2l, parsing = 0;
	unsigned *n2b;
	short unsigned *n2s;
	
	char *base = buf;
	
	while (*fmt != 0) {
		if (*fmt != '%' && !parsing) {
		    fmt++;
		} else {
			if (*fmt == '%') {
				fmt++;
				parsing = 1;
				size = STD_SIZE;
				suppress = 0;
				w = 0;
				flag = 0;
				l = 0;
			}
			
			switch(*fmt) {
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
				case '0':
					if (parsing == 1) {
						w = strtou(fmt,10,&base);
						flag |= SPACE_PAD;
						fmt = base-1;
					}
					break;
				case 'c':
					c = *buf++;
					c_ptr = va_arg(parms, char *);
					*c_ptr = c;
					scanned++;
					parsing = 0;
					break;
				case 's':
					c_ptr = va_arg(parms, char *);
					while (*buf != 0 && isspace(*buf)) {
						buf++;
					}
					
					l = 0;
					while (*buf != 0 && !isspace(*buf)) {
						if (!(flag & SPACE_PAD)) {
							*c_ptr++ = *buf;
						} else if (l < w) {
							*c_ptr++ = *buf;
							l++;
						}
						buf++;
					}
					
					*c_ptr = 0;
					scanned++;
					parsing = 0;
					break;
				case 'i':
				case 'd':
					buf = strscn(buf,"1234567890-+");
					n1 = strtoi(buf, 10, &base);
					buf = base;
					
					if (!suppress) {
						switch (size) {
							case STD_SIZE:
								n1b = va_arg(parms, int *);
								*n1b = (int)n1;
								break;
							case LONG_SIZE:
								n1l = va_arg(parms, long int *);
								*n1l = n1;
								break;
							case SHORT_SIZE:
								n1s = va_arg(parms, short int *);
								*n1s = (short)(n1);
								break;
						}
						
						scanned++;
					}
					
					parsing = 0;
					break;
				case 'u':
					buf = strscn(buf,"1234567890");
					n2 = strtou(buf, 10, &base);
					buf = base;
					if (!suppress) {
						switch (size) {
							case STD_SIZE:
								n2b = va_arg(parms, unsigned *);
								*n2b = (unsigned)n2;
								break;
							case LONG_SIZE:
								n2l = va_arg(parms, long unsigned *);
								*n2l = n2;
								break;
							case SHORT_SIZE:
								n2s = va_arg(parms, short unsigned *);
								*n2s = (short)(n2);
								break;
						}
					
						scanned++;
					}
					
					parsing = 0;
					break;
				case 'x':
					buf = strscn(buf,"1234567890xabcdefABCDEF");
					n2 = strtou(buf,16,&base);
					buf = base;
					if (!suppress) {
						switch (size) {
							case STD_SIZE:
								n2b = va_arg(parms, unsigned *);
								*n2b = (unsigned)n2;
								break;
							case LONG_SIZE:
								n2l = va_arg(parms, long unsigned *);
								*n2l = n2;
								break;
							case SHORT_SIZE:
								n2s = va_arg(parms, short unsigned *);
								*n2s = (short)(n2);
								break;
						}
					
						scanned++;
					}
					
					parsing = 0;
					break;
				case 'l':
					size = LONG_SIZE;
					break;
				case 'h':
				case 'n':
					size = SHORT_SIZE;
					break;
				case '*':
					suppress = 1;
					break;
				default:
					parsing = 0;
					break;
			}
			fmt++;
		}
	}
	
	return scanned;
}

int sscanf(char *buf, char *fmt, ...) {
	va_list parms;
	int result;
	
	va_start(parms, fmt);
	result = vsscanf(buf, fmt, parms);
	va_end(parms);
	
	return result;
}
